#ifndef CLISTENERIMPL_H
#define CLISTENERIMPL_H

#include <functional>
#include <string>
#include <unordered_map>
#include <mutex>
#include <vector>

#include "HPSocket.h"

using ConnectCallback = std::function<void(char*ip,int ip_len,u_int16_t port,bool conn)>;
using MessageCallback = std::function<void(char* data,int data_len)>;

class CListenerImpl:public CTcpClientListener
{
public:
    virtual EnHandleResult OnPrepareConnect(ITcpClient*pSender,CONNID dwConnID,SOCKET socket)override;
    virtual EnHandleResult OnConnect(ITcpClient *pSender, CONNID dwConnID) override;
    virtual EnHandleResult OnHandShake(ITcpClient* pSender,CONNID dwConnID)override;
    virtual EnHandleResult OnReceive(ITcpClient* pSender, CONNID dwConnID, const BYTE* pData, int iLength)override;
    virtual EnHandleResult OnSend(ITcpClient*pSender,CONNID dwConnID,const BYTE*pData,int iLenght)override;
    virtual EnHandleResult OnClose(ITcpClient*pSender,CONNID dwConnID,EnSocketOperation enOperation,int iErrorCode)override;
    void SetConnectCB(ConnectCallback cb){m_conn_cb = cb;}
    void SetMessageCB(MessageCallback cb){m_msg_cb = cb;};
private:
    bool m_connected{false};
    ConnectCallback m_conn_cb{};
    MessageCallback m_msg_cb{};
};

struct ConnContext{
    uint32_t total_size{};
    uint32_t received_size{};
    bool header_done{false};
    std::vector<uint8_t>buffer;
};

class ServerListenerImpl:public CTcpServerListener
{
public:
    virtual EnHandleResult OnPrepareListen(ITcpServer*pServer,SOCKET socket)override;
    virtual EnHandleResult OnAccept(ITcpServer*pServer,CONNID dwConnID,UINT_PTR soClient)override;
    virtual EnHandleResult OnHandShake(ITcpServer*pServer,CONNID dwConnID)override;
    virtual EnHandleResult OnReceive(ITcpServer*pServer,CONNID dwConnID,const BYTE*pData,int iLength)override;
    virtual EnHandleResult OnSend(ITcpServer*pServer,CONNID dwConnID,const BYTE*pData,int iLength)override;
    virtual EnHandleResult OnClose(ITcpServer*pServer,CONNID dwConnID,EnSocketOperation enOperation,int iErrorCode)override;
    virtual EnHandleResult OnShutdown(ITcpServer* pSender)override;
    void SetConnectCB(ConnectCallback cb){m_conn_cb = cb;}
    void SetMessageCB(MessageCallback cb){m_msg_cb = cb;};
    auto GetClientConnInfo(){return m_conn_hash;}
private:
    CONNID GetConnID(std::string client_info);
    std::string GetClientInfo(std::string&ip,uint16_t port);
private:
    ConnectCallback m_conn_cb{};
    MessageCallback m_msg_cb{};
    std::unordered_map<std::string,CONNID>m_conn_hash{};
    std::mutex m_mutex;
    std::mutex m_conn_mutex{};
    std::unordered_map<CONNID,ConnContext>m_conn_map{};
};


class CClientPullListener:public CTcpPullClientListener
{
public:
    virtual EnHandleResult OnConnect(ITcpClient* pSender,CONNID dwConnID)override;
    virtual EnHandleResult OnReceive(ITcpClient* pSender, CONNID dwConnID,int iLength)override;
    virtual EnHandleResult OnClose(ITcpClient*pSender,CONNID dwConnID,EnSocketOperation enOperation,int iErrorCode)override;
    void SetConnectCB(ConnectCallback cb){m_conn_cb = cb;}
    void SetMessageCB(MessageCallback cb){m_msg_cb = cb;}
private:
    MessageCallback m_msg_cb{};
    ConnectCallback m_conn_cb{};
};

#endif // CLISTENERIMPL_H
